package com.starsea.book.ui.book.read

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.content.res.Configuration
import android.net.Uri
import android.os.Bundle
import android.view.*
import androidx.activity.addCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.GravityCompat
import androidx.core.view.get
import androidx.core.view.isVisible
import androidx.core.view.size
import androidx.lifecycle.lifecycleScope
import com.blankj.utilcode.util.FragmentUtils
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
import com.starsea.book.BuildConfig
import com.starsea.book.R
import com.starsea.book.constant.*
import com.starsea.book.data.appDb
import com.starsea.book.data.entities.Book
import com.starsea.book.data.entities.BookChapter
import com.starsea.book.data.entities.BookProgress
import com.starsea.book.data.entities.BookSource
import com.starsea.book.exception.NoStackTraceException
import com.starsea.book.help.AppWebDav
import com.starsea.book.help.IntentData
import com.starsea.book.help.TTS
import com.starsea.book.help.book.*
import com.starsea.book.help.config.AppConfig
import com.starsea.book.help.config.ReadBookConfig
import com.starsea.book.help.config.ReadTipConfig
import com.starsea.book.help.coroutine.Coroutine
import com.starsea.book.help.storage.Backup
import com.starsea.book.lib.dialogs.SelectItem
import com.starsea.book.lib.dialogs.alert
import com.starsea.book.lib.theme.accentColor
import com.starsea.book.model.ReadAloud
import com.starsea.book.model.ReadBook
import com.starsea.book.model.ReadBook.restoreLastBookProcess
import com.starsea.book.model.analyzeRule.AnalyzeRule
import com.starsea.book.receiver.TimeBatteryReceiver
import com.starsea.book.service.BaseReadAloudService
import com.starsea.book.ui.about.AppLogDialog
import com.starsea.book.ui.book.audio.AudioPlayActivity
import com.starsea.book.ui.book.bookmark.BookmarkDialog
import com.starsea.book.ui.book.changesource.ChangeBookSourceDialog
import com.starsea.book.ui.book.changesource.ChangeChapterSourceDialog
import com.starsea.book.ui.book.read.config.*
import com.starsea.book.ui.book.read.config.BgTextConfigDialog.Companion.BG_COLOR
import com.starsea.book.ui.book.read.config.BgTextConfigDialog.Companion.TEXT_COLOR
import com.starsea.book.ui.book.read.config.TipConfigDialog.Companion.TIP_COLOR
import com.starsea.book.ui.book.read.config.TipConfigDialog.Companion.TIP_DIVIDER_COLOR
import com.starsea.book.ui.book.read.page.ContentTextView
import com.starsea.book.ui.book.read.page.ReadView
import com.starsea.book.ui.book.read.page.entities.PageDirection
import com.starsea.book.ui.book.read.page.provider.TextPageFactory
import com.starsea.book.ui.book.searchContent.SearchContentActivity
import com.starsea.book.ui.book.searchContent.SearchResult
import com.starsea.book.ui.book.source.edit.BookSourceEditActivity
import com.starsea.book.ui.book.toc.TocActivityResult
import com.starsea.book.ui.book.toc.TocFragment
import com.starsea.book.ui.book.toc.TocViewModel
import com.starsea.book.ui.book.toc.rule.TxtTocRuleDialog
import com.starsea.book.ui.browser.WebViewActivity
import com.starsea.book.ui.dict.DictDialog
import com.starsea.book.ui.file.HandleFileContract
import com.starsea.book.ui.login.SourceLoginActivity
import com.starsea.book.ui.newpage.CommentListAllActivity
import com.starsea.book.ui.newpage.LoginActivity
import com.starsea.book.ui.newpage.entity.EventEntity
import com.starsea.book.ui.newpage.utils.Singleton
import com.starsea.book.ui.replace.ReplaceRuleActivity
import com.starsea.book.ui.replace.edit.ReplaceEditActivity
import com.starsea.book.ui.widget.PopupAction
import com.starsea.book.ui.widget.dialog.PhotoDialog
import com.starsea.book.ui.widget.dialog.TextDialog
import com.starsea.book.utils.*
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO

/**
 * 阅读界面
 */
class ReadBookActivity : BaseReadBookActivity(),
    View.OnTouchListener,
    ReadView.CallBack,
    TextActionMenu.CallBack,
    ContentTextView.CallBack,
    PopupMenu.OnMenuItemClickListener,
    ReadMenu.CallBack,
    SearchMenu.CallBack,
    ReadAloudDialog.CallBack,
    ChangeBookSourceDialog.CallBack,
    ChangeChapterSourceDialog.CallBack,
    ReadBook.CallBack,
    AutoReadDialog.CallBack,
    TxtTocRuleDialog.CallBack,
    ColorPickerDialogListener {

    private val tocActivity =
        registerForActivityResult(TocActivityResult()) {
            it?.let {
                viewModel.openChapter(it.first, it.second)
            }
        }
    private val sourceEditActivity =
        registerForActivityResult(StartActivityContract(BookSourceEditActivity::class.java)) {
            if (it.resultCode == RESULT_OK) {
                viewModel.upBookSource {
                    upMenuView()
                }
            }
        }
    private val replaceActivity =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            it ?: return@registerForActivityResult
            if (it.resultCode == RESULT_OK) {
                viewModel.replaceRuleChanged()
            }
        }
    private val searchContentActivity =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            it ?: return@registerForActivityResult
            it.data?.let { data ->
                val key = data.getLongExtra("key", System.currentTimeMillis())
                val index = data.getIntExtra("index", 0)
                val searchResult = IntentData.get<SearchResult>("searchResult$key")
                val searchResultList = IntentData.get<List<SearchResult>>("searchResultList$key")
                if (searchResult != null && searchResultList != null) {
                    viewModel.searchContentQuery = searchResult.query
                    binding.searchMenu.upSearchResultList(searchResultList)
                    isShowingSearchResult = true
                    viewModel.searchResultIndex = index
                    binding.searchMenu.updateSearchResultIndex(index)
                    binding.searchMenu.selectedSearchResult?.let { currentResult ->
                        ReadBook.saveCurrentBookProcess() //退出全文搜索恢复此时进度
                        skipToSearch(currentResult)
                        showActionMenu()
                    }
                }
            }
        }
    private val selectImageDir = registerForActivityResult(HandleFileContract()) {
        it.uri?.let { uri ->
            ACache.get().put(AppConst.imagePathKey, uri.toString())
            viewModel.saveImage(it.value, uri)
        }
    }
    var inTimeStamp = 0L
    private var menu: Menu? = null
    private var backupJob: Job? = null
    private var keepScreenJon: Job? = null
    private var tts: TTS? = null
    val textActionMenu: TextActionMenu by lazy {
        TextActionMenu(this, this)
    }
    private val popupAction: PopupAction by lazy {
        PopupAction(this)
    }
    override val isInitFinish: Boolean get() = viewModel.isInitFinish
    override val isScroll: Boolean get() = binding.readView.isScroll
    override var autoPageProgress = 0
    override var isAutoPage = false
    override var isShowingSearchResult = false
    override var isSelectingSearchResult = false
        set(value) {
            field = value && isShowingSearchResult
        }
    private val timeBatteryReceiver = TimeBatteryReceiver()
    private var screenTimeOut: Long = 0
    private var loadStates: Boolean = false
    override val pageFactory: TextPageFactory get() = binding.readView.pageFactory
    override val headerHeight: Int get() = binding.readView.curPage.headerHeight
    private val menuLayoutIsVisible get() = bottomDialog > 0 || binding.readMenu.isVisible
    private val nextPageRunnable by lazy { Runnable { mouseWheelPage(PageDirection.NEXT) } }
    private val prevPageRunnable by lazy { Runnable { mouseWheelPage(PageDirection.PREV) } }
    private var bookChanged = false
    private var pageChanged = false
    private var reloadContent = false
    private val autoPageRenderer by lazy { SyncedRenderer { doAutoPage(it) } }
    private var autoPageScrollOffset = 0.0

    val inTime = Singleton.getFullTime(System.currentTimeMillis())

    //恢复跳转前进度对话框的交互结果
    private var confirmRestoreProcess: Boolean? = null

    @SuppressLint("ClickableViewAccessibility")
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        binding.cursorLeft.setColorFilter(accentColor)
        binding.cursorRight.setColorFilter(accentColor)
        binding.cursorLeft.setOnTouchListener(this)
        binding.cursorRight.setOnTouchListener(this)
        window.setBackgroundDrawable(null)
        inTimeStamp = System.currentTimeMillis()
        upScreenTimeOut()
        ReadBook.callBack?.notifyBookChanged()
        ReadBook.callBack = this
        onBackPressedDispatcher.addCallback(this) {
            if (isShowingSearchResult) {
                exitSearchMenu()
                restoreLastBookProcess()
                return@addCallback
            }
            //拦截返回供恢复阅读进度
            if (ReadBook.lastBookPress != null && confirmRestoreProcess != false) {
                restoreLastBookProcess()
                return@addCallback
            }
            if (BaseReadAloudService.isPlay()) {
                ReadAloud.pause(this@ReadBookActivity)
                toastOnUi(R.string.read_aloud_pause)
                return@addCallback
            }
            if (isAutoPage) {
                autoPageStop()
                return@addCallback
            }
            if (getPrefBoolean("disableReturnKey") && !menuLayoutIsVisible) {
                return@addCallback
            }
            finish()
        }

        viewModel.addSherfResult.observe(this@ReadBookActivity) {

            if (it.status == 200) {
                ReadBook.inBookshelf = true
                setResult(Activity.RESULT_OK)
                toastOnUi("加入书架成功")
            } else if (it.status == 401) {
                toastOnUi("登录过期,请重新登录")
                LoginActivity.start(this@ReadBookActivity)
            } else {
                toastOnUi(it.msg)
//                super.finish()
            }
        }
        binding.root.postDelayed({
            if (intent.getBooleanExtra("isReadAloud", false)) {
                binding.readMenu.startReadAloud()
            }
        }, 2000)
    }

    override fun onPostCreate(savedInstanceState: Bundle?) {
        super.onPostCreate(savedInstanceState)
        com.blankj.utilcode.util.LogUtils.e(">>>>> onPostCreate")
        viewModel.initData(intent) {
            initDrawerFragment()
            upMenu()
            if (reloadContent) {
                reloadContent = false
                ReadBook.loadContent(resetPageOffset = false)
            }
        }
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        com.blankj.utilcode.util.LogUtils.e(">>>>> onNewIntent")
        viewModel.initData(intent ?: return) {
            upMenu()
            if (reloadContent) {
                reloadContent = false
                ReadBook.loadContent(resetPageOffset = false)
            }
        }
    }

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        upSystemUiVisibility()
        if (hasFocus) {
            binding.readMenu.upBrightnessState()
        }
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        upSystemUiVisibility()
        binding.readView.upStatusBar()
    }

    @SuppressLint("UnspecifiedRegisterReceiverFlag")
    override fun onResume() {
        super.onResume()
        ReadBook.readStartTime = System.currentTimeMillis()
        if (bookChanged) {
            bookChanged = false
            ReadBook.callBack = this
            com.blankj.utilcode.util.LogUtils.e(">>>>> onResume")
            viewModel.initData(intent) {
                upMenu()
            }
        } else {
            //web端阅读时，app处于阅读界面，本地记录会覆盖web保存的进度，在此处恢复
            ReadBook.webBookProgress?.let {
                ReadBook.setProgress(it)
                ReadBook.webBookProgress = null
            }
        }
        upSystemUiVisibility()
        registerReceiver(timeBatteryReceiver, timeBatteryReceiver.filter)
        binding.readView.upTime()
    }

    override fun onPause() {
        super.onPause()
        autoPageStop()
        backupJob?.cancel()
        ReadBook.saveRead()
        unregisterReceiver(timeBatteryReceiver)
        upSystemUiVisibility()
        if (!BuildConfig.DEBUG) {
            ReadBook.uploadProgress()
            Backup.autoBack(this)
        }
    }

    override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.book_read, menu)
        menu.iconItemOnLongClick(R.id.menu_change_source) {
            PopupMenu(this, it).apply {
                inflate(R.menu.book_read_change_source)
                this.menu.applyOpenTint(this@ReadBookActivity)
                setOnMenuItemClickListener(this@ReadBookActivity)
            }.show()
        }
        menu.iconItemOnLongClick(R.id.menu_refresh) {
            PopupMenu(this, it).apply {
                inflate(R.menu.book_read_refresh)
                this.menu.applyOpenTint(this@ReadBookActivity)
                setOnMenuItemClickListener(this@ReadBookActivity)
            }.show()
        }
        binding.readMenu.refreshMenuColorFilter()
        return super.onCompatCreateOptionsMenu(menu)
    }

    override fun onPrepareOptionsMenu(menu: Menu): Boolean {
        this.menu = menu
        upMenu()
        return super.onPrepareOptionsMenu(menu)
    }

    override fun onMenuOpened(featureId: Int, menu: Menu): Boolean {
//        menu.findItem(R.id.menu_same_title_removed)?.isChecked =
//            ReadBook.curTextChapter?.sameTitleRemoved == true
        return super.onMenuOpened(featureId, menu)
    }

    /**
     * 更新菜单
     */
    private fun upMenu() {
        val menu = menu ?: return
        val book = ReadBook.book ?: return
        val onLine = !book.isLocal
        for (i in 0 until menu.size) {
            val item = menu[i]
            when (item.groupId) {
                R.id.menu_group_on_line -> item.isVisible = onLine
//                R.id.menu_group_local -> item.isVisible = !onLine
//                R.id.menu_group_text -> item.isVisible = book.isLocalTxt
                else -> when (item.itemId) {
                    R.id.menu_enable_replace -> item.isChecked = book.getUseReplaceRule()
//                    R.id.menu_re_segment -> item.isChecked = book.getReSegment()
//                    R.id.menu_enable_review -> {
//                        item.isVisible = BuildConfig.DEBUG
//                        item.isChecked = AppConfig.enableReview
//                    }

//                    R.id.menu_reverse_content -> item.isVisible = onLine
                }
            }
        }
//        lifecycleScope.launch {
//            menu.findItem(R.id.menu_get_progress)?.isVisible = withContext(IO) {
//                AppWebDav.isOk
//            }
//        }
    }

    /**
     * 菜单
     */
    override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.menu_book_comment -> {
                openComment()
            }

            R.id.menu_add_to_shelf -> {

                if (ReadBook.inBookshelf) {
                    toastOnUi("已在书架中")

                } else
                    viewModel.addToShelf(
                        intent.getStringExtra("bookUrl") ?: "",
                        sectionId = ReadBook.curTextChapter?.chapter?.url ?: "",
                        sectionTitle = ReadBook.curTextChapter?.chapter?.title ?: ""
                    )
            }

            R.id.menu_change_source,
            R.id.menu_book_change_source -> {
                binding.readMenu.runMenuOut()
                ReadBook.book?.let {
                    showDialogFragment(ChangeBookSourceDialog(it.name, it.author))
                }
            }

            R.id.menu_chapter_change_source -> lifecycleScope.launch {
                val book = ReadBook.book ?: return@launch
                val chapter =
                    appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
                        ?: return@launch
                binding.readMenu.runMenuOut()
                showDialogFragment(
                    ChangeChapterSourceDialog(book.name, book.author, chapter.index, chapter.title)
                )
            }

            R.id.menu_refresh,
            R.id.menu_refresh_dur -> {
                if (ReadBook.bookSource == null) {
                    upContent()
                } else {
                    ReadBook.book?.let {
                        ReadBook.curTextChapter = null
                        binding.readView.upContent()
                        viewModel.refreshContentDur(it)
                    }
                }
            }

            R.id.menu_refresh_after -> {
                if (ReadBook.bookSource == null) {
                    upContent()
                } else {
                    ReadBook.book?.let {
                        ReadBook.clearTextChapter()
                        binding.readView.upContent()
                        viewModel.refreshContentAfter(it)
                    }
                }
            }

            R.id.menu_refresh_all -> {
                if (ReadBook.bookSource == null) {
                    upContent()
                } else {
                    ReadBook.book?.let {
                        ReadBook.clearTextChapter()
                        binding.readView.upContent()
                        viewModel.refreshContentAll(it)
                    }
                }
            }

            R.id.menu_download -> showDownloadDialog()
            R.id.menu_add_bookmark -> addBookmark()
//            R.id.menu_edit_content -> showDialogFragment(ContentEditDialog())
//            R.id.menu_update_toc -> ReadBook.book?.let {
//                if (it.isEpub) {
//                    BookHelp.clearCache(it)
//                }
//                loadChapterList(it)
//            }

            R.id.menu_enable_replace -> changeReplaceRuleState()
//            R.id.menu_re_segment -> ReadBook.book?.let {
//                it.setReSegment(!it.getReSegment())
//                menu?.findItem(R.id.menu_re_segment)?.isChecked = it.getReSegment()
//                ReadBook.loadContent(false)
//            }

//            R.id.menu_enable_review -> {
//                AppConfig.enableReview = !AppConfig.enableReview
//                menu?.findItem(R.id.menu_enable_review)?.isChecked = AppConfig.enableReview
//                ReadBook.loadContent(false)
//            }
//
//            R.id.menu_page_anim -> showPageAnimConfig {
//                binding.readView.upPageAnim()
//                ReadBook.loadContent(false)
//            }

            R.id.menu_log -> showDialogFragment<AppLogDialog>()
//            R.id.menu_toc_regex -> showDialogFragment(
//                TxtTocRuleDialog(ReadBook.book?.tocUrl)
//            )
//
//            R.id.menu_reverse_content -> ReadBook.book?.let {
//                viewModel.reverseContent(it)
//            }
//
//            R.id.menu_set_charset -> showCharsetConfig()
//            R.id.menu_image_style -> {
//                val imgStyles =
//                    arrayListOf(Book.imgStyleDefault, Book.imgStyleFull, Book.imgStyleText)
//                selector(
//                    R.string.image_style,
//                    imgStyles
//                ) { _, index ->
//                    ReadBook.book?.setImageStyle(imgStyles[index])
//                    ReadBook.loadContent(false)
//                }
//            }
//
//            R.id.menu_get_progress -> ReadBook.book?.let {
//                viewModel.syncBookProgress(it) { progress ->
//                    sureSyncProgress(progress)
//                }
//            }

//            R.id.menu_same_title_removed -> {
//                ReadBook.book?.let {
//                    val contentProcessor = ContentProcessor.get(it)
//                    val textChapter = ReadBook.curTextChapter
//                    if (textChapter != null
//                        && !textChapter.sameTitleRemoved
//                        && !contentProcessor.removeSameTitleCache.contains(
//                            textChapter.chapter.getFileName("nr")
//                        )
//                    ) {
//                        toastOnUi("未找到可移除的重复标题")
//                    }
//                }
//                viewModel.reverseRemoveSameTitle()
//            }

//            R.id.menu_effective_replaces -> showDialogFragment<EffectiveReplacesDialog>()

            R.id.menu_help -> showReadMenuHelp()
        }
        return super.onCompatOptionsItemSelected(item)
    }

    override fun onMenuItemClick(item: MenuItem): Boolean {
        return onCompatOptionsItemSelected(item)
    }

    /**
     * 按键拦截,显示菜单
     */
    override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
        val keyCode = event?.keyCode
        val action = event?.action
        val isDown = action == 0

        if (keyCode == KeyEvent.KEYCODE_MENU) {
            if (isDown && !binding.readMenu.canShowMenu) {
                binding.readMenu.runMenuIn()
                return true
            }
            if (!isDown && !binding.readMenu.canShowMenu) {
                binding.readMenu.canShowMenu = true
                return true
            }
        }
        return super.dispatchKeyEvent(event)
    }

    /**
     * 鼠标滚轮事件
     */
    override fun onGenericMotionEvent(event: MotionEvent): Boolean {
        if (0 != (event.source and InputDevice.SOURCE_CLASS_POINTER)) {
            if (event.action == MotionEvent.ACTION_SCROLL) {
                val axisValue = event.getAxisValue(MotionEvent.AXIS_VSCROLL)
                LogUtils.d("onGenericMotionEvent", "axisValue = $axisValue")
                binding.root.removeCallbacks(nextPageRunnable)
                binding.root.removeCallbacks(prevPageRunnable)
                // 获得垂直坐标上的滚动方向
                if (axisValue < 0.0f) { // 滚轮向下滚
                    binding.root.postDelayed(nextPageRunnable, 200)
                } else { // 滚轮向上滚
                    binding.root.postDelayed(prevPageRunnable, 200)
                }
                return true
            }
        }
        return super.onGenericMotionEvent(event)
    }

    /**
     * 按键事件
     */
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (menuLayoutIsVisible) {
            return super.onKeyDown(keyCode, event)
        }
        when {
            isPrevKey(keyCode) -> {
                if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
                    binding.readView.cancelSelect()
                    binding.readView.pageDelegate?.keyTurnPage(PageDirection.PREV)
                    return true
                }
            }

            isNextKey(keyCode) -> {
                if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
                    binding.readView.cancelSelect()
                    binding.readView.pageDelegate?.keyTurnPage(PageDirection.NEXT)
                    return true
                }
            }

            keyCode == KeyEvent.KEYCODE_VOLUME_UP -> {
                if (volumeKeyPage(PageDirection.PREV)) {
                    return true
                }
            }

            keyCode == KeyEvent.KEYCODE_VOLUME_DOWN -> {
                if (volumeKeyPage(PageDirection.NEXT)) {
                    return true
                }
            }

            keyCode == KeyEvent.KEYCODE_PAGE_UP -> {
                binding.readView.cancelSelect()
                binding.readView.pageDelegate?.keyTurnPage(PageDirection.PREV)
                return true
            }

            keyCode == KeyEvent.KEYCODE_PAGE_DOWN -> {
                binding.readView.cancelSelect()
                binding.readView.pageDelegate?.keyTurnPage(PageDirection.NEXT)
                return true
            }

            keyCode == KeyEvent.KEYCODE_SPACE -> {
                binding.readView.cancelSelect()
                binding.readView.pageDelegate?.keyTurnPage(PageDirection.NEXT)
                return true
            }

        }
        return super.onKeyDown(keyCode, event)
    }

    /**
     * 松开按键事件
     */
    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        when (keyCode) {
            KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN -> {
                if (volumeKeyPage(PageDirection.NONE)) {
                    return true
                }
            }

        }
        return super.onKeyUp(keyCode, event)
    }

    /**
     * view触摸,文字选择
     */
    @SuppressLint("ClickableViewAccessibility")
    override fun onTouch(v: View, event: MotionEvent): Boolean = binding.run {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> textActionMenu.dismiss()
            MotionEvent.ACTION_MOVE -> {
                when (v.id) {
                    R.id.cursor_left -> if (!readView.curPage.getReverseStartCursor()) {
                        readView.curPage.selectStartMove(
                            event.rawX + cursorLeft.width,
                            event.rawY - cursorLeft.height
                        )
                    } else {
                        readView.curPage.selectEndMove(
                            event.rawX - cursorRight.width,
                            event.rawY - cursorRight.height
                        )
                    }

                    R.id.cursor_right -> if (readView.curPage.getReverseEndCursor()) {
                        readView.curPage.selectStartMove(
                            event.rawX + cursorLeft.width,
                            event.rawY - cursorLeft.height
                        )
                    } else {
                        readView.curPage.selectEndMove(
                            event.rawX - cursorRight.width,
                            event.rawY - cursorRight.height
                        )
                    }
                }
            }

            MotionEvent.ACTION_UP -> {
                readView.curPage.resetReverseCursor()
                showTextActionMenu()
            }
        }
        return true
    }

    /**
     * 更新文字选择开始位置
     */
    override fun upSelectedStart(x: Float, y: Float, top: Float) = binding.run {
        cursorLeft.x = x - cursorLeft.width
        cursorLeft.y = y
        cursorLeft.visible(true)
        textMenuPosition.x = x
        textMenuPosition.y = top
    }

    /**
     * 更新文字选择结束位置
     */
    override fun upSelectedEnd(x: Float, y: Float) = binding.run {
        cursorRight.x = x
        cursorRight.y = y
        cursorRight.visible(true)
    }

    /**
     * 取消文字选择
     */
    override fun onCancelSelect() = binding.run {
        cursorLeft.invisible()
        cursorRight.invisible()
        textActionMenu.dismiss()
    }

    override fun onLongScreenshotTouchEvent(event: MotionEvent): Boolean {
        return binding.readView.onTouchEvent(event)
    }

    /**
     * 显示文本操作菜单
     */
    override fun showTextActionMenu() {
        //隐藏
        if (true) {
            return
        }

        val navigationBarHeight =
            if (!ReadBookConfig.hideNavigationBar && navigationBarGravity == Gravity.BOTTOM)
                navigationBarHeight else 0
        textActionMenu.show(
            binding.textMenuPosition,
            binding.root.height + navigationBarHeight,
            binding.textMenuPosition.x.toInt(),
            binding.textMenuPosition.y.toInt(),
            binding.cursorLeft.y.toInt() + binding.cursorLeft.height,
            binding.cursorRight.x.toInt(),
            binding.cursorRight.y.toInt() + binding.cursorRight.height
        )
    }

    /**
     * 当前选择的文本
     */
    override val selectedText: String get() = binding.readView.getSelectText()

    /**
     * 文本选择菜单操作
     */
    override fun onMenuItemSelected(itemId: Int): Boolean {
        when (itemId) {
            R.id.menu_aloud -> when (AppConfig.contentSelectSpeakMod) {
                1 -> binding.readView.aloudStartSelect()
                else -> speak(binding.readView.getSelectText())
            }

            R.id.menu_bookmark -> binding.readView.curPage.let {
                val bookmark = it.createBookmark()
                if (bookmark == null) {
                    toastOnUi(R.string.create_bookmark_error)
                } else {
                    showDialogFragment(BookmarkDialog(bookmark))
                }
                return true
            }

            R.id.menu_replace -> {
                val scopes = arrayListOf<String>()
                ReadBook.book?.name?.let {
                    scopes.add(it)
                }
                ReadBook.bookSource?.bookSourceUrl?.let {
                    scopes.add(it)
                }
                replaceActivity.launch(
                    ReplaceEditActivity.startIntent(
                        this,
                        pattern = selectedText,
                        scope = scopes.joinToString(";")
                    )
                )
                return true
            }

            R.id.menu_search_content -> {
                viewModel.searchContentQuery = selectedText
                openSearchActivity(selectedText)
                return true
            }

            R.id.menu_dict -> {
                showDialogFragment(DictDialog(selectedText))
                return true
            }
        }
        return false
    }

    /**
     * 文本选择菜单操作完成
     */
    override fun onMenuActionFinally() = binding.run {
        textActionMenu.dismiss()
        readView.curPage.cancelSelect()
        readView.isTextSelected = false
    }

    private fun speak(text: String) {
        if (tts == null) {
            tts = TTS()
        }
        tts?.speak(text)
    }

    /**
     * 鼠标滚轮翻页
     */
    private fun mouseWheelPage(direction: PageDirection): Boolean {
        if (!binding.readMenu.isVisible) {
            if (getPrefBoolean("mouseWheelPage", true)) {
                binding.readView.pageDelegate?.isCancel = false
                binding.readView.pageDelegate?.keyTurnPage(direction)
                return true
            }
        }
        return false
    }

    /**
     * 音量键翻页
     */
    private fun volumeKeyPage(direction: PageDirection): Boolean {
        if (!binding.readMenu.isVisible) {
            if (getPrefBoolean("volumeKeyPage", true)) {
                if (getPrefBoolean("volumeKeyPageOnPlay")
                    || !BaseReadAloudService.isPlay()
                ) {
                    binding.readView.cancelSelect()
                    binding.readView.pageDelegate?.isCancel = false
                    binding.readView.pageDelegate?.keyTurnPage(direction)
                    return true
                }
            }
        }
        return false
    }

    override fun upMenuView() {
        lifecycleScope.launch {
            binding.readMenu.upBookView()
        }
    }

    override fun loadChapterList(book: Book) {
        ReadBook.upMsg(getString(R.string.toc_updateing))
        viewModel.loadChapterList(book)
    }

    /**
     * 内容加载完成
     */
    override fun contentLoadFinish() {
        if (intent.getBooleanExtra("readAloud", false)) {
            intent.removeExtra("readAloud")
            ReadBook.readAloud()
        }
        if (BaseReadAloudService.isRun) {
            ReadAloud.upTtsProgress(this)
        }
        loadStates = true
    }

    /**
     * 更新内容
     */
    override fun upContent(
        relativePosition: Int,
        resetPageOffset: Boolean,
        success: (() -> Unit)?
    ) {
        lifecycleScope.launch {
            if (relativePosition == 0) {
                autoPageProgress = 0
            }
            binding.readView.upContent(relativePosition, resetPageOffset)
            upSeekBarProgress()
            loadStates = false
            success?.invoke()
        }
    }

    override fun upPageAnim() {
        lifecycleScope.launch {
            binding.readView.upPageAnim()
        }
    }

    override fun notifyBookChanged() {
        bookChanged = true
    }

    /**
     * 页面改变
     */
    override fun pageChanged() {
        pageChanged = true
        lifecycleScope.launch {
            autoPageProgress = 0
            upSeekBarProgress()
            startBackupJob()
        }
    }

    /**
     * 更新进度条位置
     */
    private fun upSeekBarProgress() {
        val progress = when (AppConfig.progressBarBehavior) {
            "page" -> ReadBook.durPageIndex
            else /* chapter */ -> ReadBook.durChapterIndex
        }
        binding.readMenu.setSeekPage(progress)
    }

    /**
     * 显示菜单
     */
    override fun showMenuBar() {
        binding.readMenu.runMenuIn()
    }

    override val oldBook: Book?
        get() = ReadBook.book

    override fun changeTo(source: BookSource, book: Book, toc: List<BookChapter>) {
        if (!book.isAudio) {
            viewModel.changeTo(book, toc)
        } else {
            ReadAloud.stop(this)
            lifecycleScope.launch {
                withContext(IO) {
                    ReadBook.book?.migrateTo(book, toc)
                    book.removeType(BookType.updateError)
                    ReadBook.book?.delete()
                    appDb.bookDao.insert(book)
                }
                startActivity<AudioPlayActivity> {
                    putExtra("bookUrl", book.bookUrl)
                }
                finish()
            }
        }
    }

    override fun replaceContent(content: String) {
        ReadBook.book?.let {
            viewModel.saveContent(it, content)
        }
    }

    override fun showActionMenu() {
        when {
            BaseReadAloudService.isRun -> showReadAloudDialog()
            isAutoPage -> showDialogFragment<AutoReadDialog>()
            isShowingSearchResult -> binding.searchMenu.runMenuIn()
            else -> binding.readMenu.runMenuIn()
        }
    }

    override fun showReadMenuHelp() {
        val text = String(assets.open("help/readMenuHelp.md").readBytes())
        showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
    }

    /**
     * 显示朗读菜单
     */
    override fun showReadAloudDialog() {
        showDialogFragment<ReadAloudDialog>()
    }

    /**
     * 自动翻页
     */
    override fun autoPage() {
        ReadAloud.stop(this)
        if (isAutoPage) {
            autoPageStop()
        } else {
            isAutoPage = true
            autoPagePlus()
            binding.readMenu.setAutoPage(true)
            screenTimeOut = -1L
            screenOffTimerStart()
        }
    }

    override fun autoPageStop() {
        if (isAutoPage) {
            isAutoPage = false
            autoPageRenderer.stop()
            binding.readView.invalidate()
            binding.readView.clearNextPageBitmap()
            binding.readMenu.setAutoPage(false)
            upScreenTimeOut()
        }
    }

    private fun autoPagePlus() {
        autoPageProgress = 0
        autoPageScrollOffset = 0.0
        autoPageRenderer.start()
    }

    private fun doAutoPage(frameTime: Double) {
        if (menuLayoutIsVisible) {
            return
        }
        if (binding.readView.run { isScroll && pageDelegate?.isRunning == true }) {
            return
        }
        val readTime = ReadBookConfig.autoReadSpeed * 1000.0
        val height = binding.readView.height
        autoPageScrollOffset += height / readTime * frameTime
        if (autoPageScrollOffset < 1) {
            return
        }
        val scrollOffset = autoPageScrollOffset.toInt()
        autoPageScrollOffset -= scrollOffset
        if (binding.readView.isScroll) {
            binding.readView.curPage.scroll(-scrollOffset)
        } else {
            autoPageProgress += scrollOffset
            if (autoPageProgress >= height) {
                autoPageProgress = 0
                if (!binding.readView.fillPage(PageDirection.NEXT)) {
                    autoPageStop()
                } else {
                    binding.readView.clearNextPageBitmap()
                }
            } else {
                binding.readView.invalidate()
            }
        }
    }

    override fun openSourceEditActivity() {
        ReadBook.bookSource?.let {
            sourceEditActivity.launch {
                putExtra("sourceUrl", it.bookSourceUrl)
            }
        }
    }

    /**
     * 替换
     */
    override fun openReplaceRule() {
        replaceActivity.launch(Intent(this, ReplaceRuleActivity::class.java))
    }

    /**
     * 打开目录
     */
    override fun openChapterList() {
//        ReadBook.book?.let {
//            tocActivity.launch(it.bookUrl)
//        }
        if (mCurrentFragment == null) {
            return
        }

        binding.drlDrawer.openDrawer(GravityCompat.START)
    }

    /**
     * 打开搜索界面
     */
    override fun openSearchActivity(searchWord: String?) {
        ReadBook.book?.let {
            searchContentActivity.launch(Intent(this, SearchContentActivity::class.java).apply {
                putExtra("bookUrl", it.bookUrl)
                putExtra("searchWord", searchWord ?: viewModel.searchContentQuery)
                putExtra("searchResultIndex", viewModel.searchResultIndex)
                viewModel.searchResultList?.first()?.let {
                    if (it.query == viewModel.searchContentQuery) {
                        IntentData.put("searchResultList", viewModel.searchResultList)
                    }
                }
            })
        }
    }

    /**
     * 禁用书源
     */
    override fun disableSource() {
        viewModel.disableSource()
    }

    /**
     * 显示阅读样式配置
     */
    override fun showReadStyle() {
        showDialogFragment<ReadStyleDialog>()
    }

    /**
     * 显示更多设置
     */
    override fun showMoreSetting() {
        showDialogFragment<MoreConfigDialog>()
    }

    override fun showSearchSetting() {
        showDialogFragment<MoreConfigDialog>()
    }

    /**
     * 更新状态栏,导航栏
     */
    override fun upSystemUiVisibility() {
        upSystemUiVisibility(isInMultiWindow, !menuLayoutIsVisible, bottomDialog > 0)
        upNavigationBarColor()
    }

    // 退出全文搜索
    override fun exitSearchMenu() {
        if (isShowingSearchResult) {
            isShowingSearchResult = false
            binding.searchMenu.invalidate()
            binding.searchMenu.invisible()
            binding.readView.isTextSelected = false
            ReadBook.curTextChapter?.clearSearchResult()
            ReadBook.prevTextChapter?.clearSearchResult()
            ReadBook.nextTextChapter?.clearSearchResult()
            binding.readView.curPage.cancelSelect(true)
        }
    }

    /* 恢复到 全文搜索/进度条跳转前的位置 */
    private fun restoreLastBookProcess() {
        if (confirmRestoreProcess == true) {
            ReadBook.restoreLastBookProcess()
        } else if (confirmRestoreProcess == null) {
            alert(R.string.draw) {
                setMessage(R.string.restore_last_book_process)
                yesButton {
                    confirmRestoreProcess = true
                    ReadBook.restoreLastBookProcess() //恢复启动全文搜索前的进度
                }
                noButton {
                    ReadBook.lastBookPress = null
                    confirmRestoreProcess = false
                }
                onCancelled {
                    ReadBook.lastBookPress = null
                    confirmRestoreProcess = false
                }
            }
        }
    }

    override fun showLogin() {
        ReadBook.bookSource?.let {
            startActivity<SourceLoginActivity> {
                putExtra("type", "bookSource")
                putExtra("key", it.bookSourceUrl)
            }
        }
    }

    override fun payAction() {
        ReadBook.book?.let { book ->
            if (book.isLocal) return
            val chapter = appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
            if (chapter == null) {
                toastOnUi("no chapter")
                return
            }
            alert(R.string.chapter_pay) {
                setMessage(chapter.title)
                yesButton {
                    Coroutine.async {
                        val source =
                            ReadBook.bookSource ?: throw NoStackTraceException("no book source")
                        val payAction = source.getContentRule().payAction
                        if (payAction.isNullOrBlank()) {
                            throw NoStackTraceException("no pay action")
                        }
                        val analyzeRule = AnalyzeRule(book, source)
                        analyzeRule.setBaseUrl(chapter.url)
                        analyzeRule.chapter = chapter
                        analyzeRule.evalJS(payAction).toString()
                    }.onSuccess {
                        if (it.isAbsUrl()) {
                            startActivity<WebViewActivity> {
                                putExtra("title", getString(R.string.chapter_pay))
                                putExtra("url", it)
                                IntentData.put(it, ReadBook.bookSource?.getHeaderMap(true))
                            }
                        } else if (it.isTrue()) {
                            //购买成功后刷新目录
                            ReadBook.book?.let {
                                ReadBook.curTextChapter = null
                                BookHelp.delContent(book, chapter)
                                viewModel.loadChapterList(book)
                            }
                        }
                    }.onError {
                        AppLog.put("执行购买操作出错\n${it.localizedMessage}", it, true)
                    }
                }
                noButton()
            }
        }
    }

    /**
     * 朗读按钮
     */
    override fun onClickReadAloud() {
        autoPageStop()
        when {
            !BaseReadAloudService.isRun -> {
                ReadAloud.upReadAloudClass()
                val scrollPageAnim = ReadBook.pageAnim() == 3
                if (scrollPageAnim) {
                    val startPos = binding.readView.getCurPagePosition()
                    ReadBook.readAloud(startPos = startPos)
                } else {
                    ReadBook.readAloud()
                }
            }

            BaseReadAloudService.pause -> {
                val scrollPageAnim = ReadBook.pageAnim() == 3
                if (scrollPageAnim && pageChanged) {
                    pageChanged = false
                    val startPos = binding.readView.getCurPagePosition()
                    ReadBook.readAloud(startPos = startPos)
                } else {
                    ReadAloud.resume(this)
                }
            }

            else -> ReadAloud.pause(this)
        }
    }

    /**
     * 长按图片
     */
    @SuppressLint("RtlHardcoded")
    override fun onImageLongPress(x: Float, y: Float, src: String) {
        popupAction.setItems(
            listOf(
                SelectItem(getString(R.string.show), "show"),
                SelectItem(getString(R.string.refresh), "refresh"),
                SelectItem(getString(R.string.action_save), "save"),
                SelectItem(getString(R.string.menu), "menu"),
                SelectItem(getString(R.string.select_folder), "selectFolder")
            )
        )
        popupAction.onActionClick = {
            when (it) {
                "show" -> showDialogFragment(PhotoDialog(src))
                "refresh" -> viewModel.refreshImage(src)
                "save" -> {
                    val path = ACache.get().getAsString(AppConst.imagePathKey)
                    if (path.isNullOrEmpty()) {
                        selectImageDir.launch {
                            value = src
                        }
                    } else {
                        viewModel.saveImage(src, Uri.parse(path))
                    }
                }

                "menu" -> showActionMenu()
                "selectFolder" -> selectImageDir.launch()
            }
            popupAction.dismiss()
        }
        val navigationBarHeight =
            if (!ReadBookConfig.hideNavigationBar && navigationBarGravity == Gravity.BOTTOM)
                navigationBarHeight else 0
        popupAction.showAtLocation(
            binding.readView, Gravity.BOTTOM or Gravity.LEFT, x.toInt(),
            binding.root.height + navigationBarHeight - y.toInt()
        )
    }

    /**
     * colorSelectDialog
     */
    override fun onColorSelected(dialogId: Int, color: Int) = ReadBookConfig.durConfig.run {
        when (dialogId) {
            TEXT_COLOR -> {
                setCurTextColor(color)
                postEvent(EventBus.UP_CONFIG, false)
            }

            BG_COLOR -> {
                setCurBg(0, "#${color.hexString}")
                postEvent(EventBus.UP_CONFIG, false)
            }

            TIP_COLOR -> {
                ReadTipConfig.tipColor = color
                postEvent(EventBus.TIP_COLOR, "")
                postEvent(EventBus.UP_CONFIG, true)
            }

            TIP_DIVIDER_COLOR -> {
                ReadTipConfig.tipDividerColor = color
                postEvent(EventBus.TIP_COLOR, "")
                postEvent(EventBus.UP_CONFIG, true)
            }
        }
    }

    /**
     * colorSelectDialog
     */
    override fun onDialogDismissed(dialogId: Int) = Unit

    override fun onTocRegexDialogResult(tocRegex: String) {
        ReadBook.book?.let {
            it.tocUrl = tocRegex
            loadChapterList(it)
        }
    }

    private fun sureSyncProgress(progress: BookProgress) {
        alert(R.string.get_book_progress) {
            setMessage(R.string.current_progress_exceeds_cloud)
            okButton {
                ReadBook.setProgress(progress)
            }
            noButton()
        }
    }

    /* 进度条跳转到指定章节 */
    override fun skipToChapter(index: Int) {
        ReadBook.saveCurrentBookProcess() //退出章节跳转恢复此时进度
        viewModel.openChapter(index)
    }

    /* 全文搜索跳转 */
    override fun navigateToSearch(searchResult: SearchResult, index: Int) {
        viewModel.searchResultIndex = index
        skipToSearch(searchResult)
    }

    /* 全文搜索跳转 */
    private fun skipToSearch(searchResult: SearchResult) {
        val previousResult = binding.searchMenu.previousSearchResult

        fun jumpToPosition() {
            val curTextChapter = ReadBook.curTextChapter ?: return
            binding.searchMenu.updateSearchInfo()
            val (pageIndex, lineIndex, charIndex, addLine, charIndex2) =
                viewModel.searchResultPositions(curTextChapter, searchResult)
            ReadBook.skipToPage(pageIndex) {
                isSelectingSearchResult = true
                binding.readView.curPage.selectStartMoveIndex(0, lineIndex, charIndex)
                when (addLine) {
                    0 -> binding.readView.curPage.selectEndMoveIndex(
                        0,
                        lineIndex,
                        charIndex + viewModel.searchContentQuery.length - 1
                    )

                    1 -> binding.readView.curPage.selectEndMoveIndex(
                        0, lineIndex + 1, charIndex2
                    )
                    //consider change page, jump to scroll position
                    -1 -> binding.readView.curPage.selectEndMoveIndex(1, 0, charIndex2)
                }
                binding.readView.isTextSelected = true
                isSelectingSearchResult = false
            }
        }

        if (searchResult.chapterIndex != previousResult?.chapterIndex) {
            viewModel.openChapter(searchResult.chapterIndex) {
                jumpToPosition()
            }
        } else {
            jumpToPosition()
        }
    }

    override fun addBookmark() {
        val book = ReadBook.book
        val page = ReadBook.curTextChapter?.getPage(ReadBook.durPageIndex)
        if (book != null && page != null) {
            val bookmark = book.createBookMark().apply {
                chapterIndex = ReadBook.durChapterIndex
                chapterPos = ReadBook.durChapterPos
                chapterName = page.title
                bookText = page.text.trim()
            }
            showDialogFragment(BookmarkDialog(bookmark))
        }
    }

    override fun changeReplaceRuleState() {
        ReadBook.book?.let {
            it.setUseReplaceRule(!it.getUseReplaceRule())
            ReadBook.saveRead()
            menu?.findItem(R.id.menu_enable_replace)?.isChecked = it.getUseReplaceRule()
            viewModel.replaceRuleChanged()
        }
    }

    private fun startBackupJob() {
        backupJob?.cancel()
        backupJob = lifecycleScope.launch(IO) {
            delay(300000)
            ReadBook.book?.let {
                AppWebDav.uploadBookProgress(it)
                it.save()
                Backup.autoBack(this@ReadBookActivity)
            }
        }
    }

    override fun finish() {
        addHsitory()
        if (!ReadBook.inBookshelf)
            viewModel.removeFromBookshelf { super.finish() }
        super.finish()


//        ReadBook.book?.let {
//            if (!ReadBook.inBookshelf) {
////                if (!AppConfig.showAddToShelfAlert) {
////                    addHsitory()
////                    viewModel.removeFromBookshelf { super.finish() }
////                } else {
//                alert(title = getString(R.string.add_to_bookshelf)) {
//                    setMessage(getString(R.string.check_add_bookshelf, it.name))
//                    okButton {
////                            ReadBook.inBookshelf = true
////                            setResult(Activity.RESULT_OK)
////                            addHsitory()
//                        addToShelf()
//                        showLoading()
//                        viewModel.addSherfResult.observe(this@ReadBookActivity) {
//                            addHsitory()
//                            if (it.status == 200) {
//                                ReadBook.inBookshelf = true
//                                setResult(Activity.RESULT_OK)
//                                toastOnUi("已加入书架")
//                                super.finish()
//                            } else if (it.status == 401) {
//                                toastOnUi("登录过期,请重新登录")
//
//                                LoginActivity.start(this@ReadBookActivity)
//                            } else {
//                                toastOnUi(it.msg)
//                                super.finish()
//                            }
//                        }
//
//                    }
//                    noButton {
//                        addHsitory()
//                        super.finish()
//                        viewModel.removeFromBookshelf { super.finish() }
//                    }
//                }
////                }
//            } else {
//                addHsitory()
//                super.finish()
//            }
//        } ?: super.finish()
    }


    override fun onDestroy() {
//        [BookChapter(url=5301033094705152, title=序, isVolume=false, baseUrl=, bookUrl=3410, index=0, isVip=false, isPay=true, resourceUrl=null, tag=null, start=null, end=null, startFragmentId=null, endFragmentId=null, variable=null), BookChapter(url=5301033270865920, title=第1章, isVolume=false, baseUrl=, bookUrl=3410, index=1, isVip=false, isPay=true, resourceUrl=null, tag=null, start=null, end=null, startFragmentId=null, endFragmentId=null, variable=null), BookChapter(url=5301033539301376, title=第2章, isVolume=false, baseUrl=, bookUrl=3410, index=2, isVip=false, isPay=true, resourceUrl=null, tag=null, start=null, end=null, startFragmentId=null, endFragmentId=null, variable=null), BookChapter(url=5301033728045056, title=第3章, isVolume=false, baseUrl=, bookUrl=3410, index=3, isVip=false, isPay=false,
//            resourceUrl=null, tag=null, start=null, end=null, startFragmentId=null, endFragmentId=null, variable=null)]


//        ReadBook.book?.let { book ->
//            LogUtils.e(">>> ",">>> sectionTitle2 = "+  book.durChapterTitle ?: "")
//            LogUtils.e(">>> ",">>> onDestroy bookUrl = "+  book.bookUrl)
//
//        }


        super.onDestroy()
        tts?.clearTts()
        textActionMenu.dismiss()
        popupAction.dismiss()
        binding.readView.onDestroy()
        ReadBook.msg = null
        if (ReadBook.callBack === this) {
            ReadBook.callBack = null
        }
        ReadBook.preDownloadTask?.cancel()
        ReadBook.downloadScope.coroutineContext.cancelChildren()
        ReadBook.coroutineContext.cancelChildren()
        ReadBook.downloadedChapters.clear()
        ReadBook.downloadFailChapters.clear()
        if (!BuildConfig.DEBUG) {
            Backup.autoBack(this)
        }
    }

    override fun observeLiveBus() = binding.run {

        observeEvent<EventEntity>(EventBus.OPEN_TO_CHAPTER) {
            viewModel.openChapter(it.index, it.chapterPos)
            binding.drlDrawer.closeDrawer(GravityCompat.START)
        }

        observeEvent<String>(EventBus.TIME_CHANGED) { readView.upTime() }
        observeEvent<Int>(EventBus.BATTERY_CHANGED) { readView.upBattery(it) }
        observeEvent<Boolean>(EventBus.MEDIA_BUTTON) {
            if (it) {
                onClickReadAloud()
            } else {
                ReadBook.readAloud(!BaseReadAloudService.pause)
            }
        }
        observeEvent<Boolean>(EventBus.UP_CONFIG) {
            upSystemUiVisibility()
            readView.upPageSlopSquare()
            readView.upBg()
            readView.upStyle()
            readView.upBgAlpha()
            if (it) {
                if (isInitFinish) {
                    ReadBook.loadContent(resetPageOffset = false)
                } else {
                    reloadContent = true
                }
            } else {
                readView.upContent(resetPageOffset = false)
            }
            binding.readMenu.reset()
        }
        observeEvent<Int>(EventBus.ALOUD_STATE) {
            if (it == Status.STOP || it == Status.PAUSE) {
                ReadBook.curTextChapter?.let { textChapter ->
                    val page = textChapter.getPageByReadPos(ReadBook.durChapterPos)
                    if (page != null) {
                        page.removePageAloudSpan()
                        readView.upContent(resetPageOffset = false)
                    }
                }
            }
        }
        observeEventSticky<Int>(EventBus.TTS_PROGRESS) { chapterStart ->
            lifecycleScope.launch(IO) {
                if (BaseReadAloudService.isPlay()) {
                    ReadBook.curTextChapter?.let { textChapter ->
                        val pageIndex = ReadBook.durPageIndex
                        val aloudSpanStart = chapterStart - textChapter.getReadLength(pageIndex)
                        textChapter.getPage(pageIndex)
                            ?.upPageAloudSpan(aloudSpanStart)
                        upContent()
                    }
                }
            }
        }
        observeEvent<Boolean>(PreferKey.keepLight) {
            upScreenTimeOut()
        }
        observeEvent<Boolean>(PreferKey.textSelectAble) {
            readView.curPage.upSelectAble(it)
        }
        observeEvent<String>(PreferKey.showBrightnessView) {
            readMenu.upBrightnessState()
        }
        observeEvent<List<SearchResult>>(EventBus.SEARCH_RESULT) {
            viewModel.searchResultList = it
        }
        observeEvent<Boolean>(EventBus.UPDATE_READ_ACTION_BAR) {
            binding.readMenu.reset()
        }
        observeEvent<Boolean>(EventBus.UP_SEEK_BAR) {
            binding.readMenu.upSeekBar()
        }
    }

    private fun upScreenTimeOut() {
        val keepLightPrefer = getPrefString(PreferKey.keepLight)?.toInt() ?: 0
        screenTimeOut = keepLightPrefer * 1000L
        screenOffTimerStart()
    }

    /**
     * 重置黑屏时间
     */
    override fun screenOffTimerStart() {
        keepScreenJon?.cancel()
        keepScreenJon = lifecycleScope.launch {
            if (screenTimeOut < 0) {
                keepScreenOn(true)
                return@launch
            }
            val t = screenTimeOut - sysScreenOffTime
            if (t > 0) {
                keepScreenOn(true)
                delay(screenTimeOut)
                keepScreenOn(false)
            } else {
                keepScreenOn(false)
            }
        }
    }


    override fun onStop() {
        super.onStop()
    }

    fun addHsitory() {
        viewModel.addReadHistory(
            bookId = intent.getStringExtra("bookUrl") ?: "",
            createTime = inTime,
            leaveTime = Singleton.getFullTime(System.currentTimeMillis()),
            sectionId = ReadBook.curTextChapter?.chapter?.url ?: "",
            sectionTitle = ReadBook.curTextChapter?.chapter?.title ?: "",
            createTimeTimestamp = inTimeStamp,
            leaveTimeTimestamp = System.currentTimeMillis()
        )
    }

    override fun addToShelf() {
        if (ReadBook.inBookshelf) {
            toastOnUi("已在书架中")
            return
        }

        viewModel.addToShelf(
            intent.getStringExtra("bookUrl") ?: "",
            sectionId = ReadBook.curTextChapter?.chapter?.url ?: "",
            sectionTitle = ReadBook.curTextChapter?.chapter?.title ?: ""
        )
    }

    override fun openComment() {
        startActivity<CommentListAllActivity> {
            putExtra("bookId", intent.getStringExtra("bookUrl") ?: "")
        }
    }


    private var mCurrentFragment: TocFragment? = null
    val viewTocModel by viewModels<TocViewModel>()

    fun initDrawerFragment() {

        intent.getStringExtra("bookUrl")?.let {
            viewTocModel.initBook(it)
        }

        viewTocModel.bookData.observe(this) {
            if (mCurrentFragment == null) {
                mCurrentFragment = TocFragment.newInstance(intent.getStringExtra("bookUrl") ?: "")
                FragmentUtils.add(supportFragmentManager, mCurrentFragment!!, R.id.fflayout_toc)
            }
        }
    }
}
